﻿using System;

namespace Cpu6502
{
    public static class CPU
    {
        public enum AddressType
        {
            Immediate,
            Absolute,
            ZeroPage,
            Implied,
            IndirectAbsolute,
            AbsoluteIndexedX,
            AbsoluteIndexedY,
            ZeroPageIndexedX,
            ZeroPageIndexedY,
            IndexedIndirect,
            IndirectIndexed,
            Relative,
            Accumulator
        }

        public static Registers Registers  = new Registers();
        public static Stack Stack = new Stack();
        public static OpcodeMapper OpcodeMapper = new OpcodeMapper();

        public static Byte[] Memory = new Byte[65536];
        
        // Program Counter
        public static Int32 PC = 0;

        public static void DumpDebug()
        {
            Console.WriteLine("Registers:");
            Console.WriteLine("\tA: " + CPU.Registers.A);
            Console.WriteLine("\tX: " + CPU.Registers.X);
            Console.WriteLine("\tY: " + CPU.Registers.Y);
            Console.WriteLine("\tS: " + CPU.Registers.S);
            Console.WriteLine("\tP: " + CPU.Registers.P.Value);
            
            Console.WriteLine("Flags:");
            Console.WriteLine("\tB: " + CPU.Registers.P.B);
            Console.WriteLine("\tC: " + CPU.Registers.P.C);
            Console.WriteLine("\tD: " + CPU.Registers.P.D);
            Console.WriteLine("\tI: " + CPU.Registers.P.I);
            Console.WriteLine("\tN: " + CPU.Registers.P.N);
            Console.WriteLine("\tV: " + CPU.Registers.P.V);
            Console.WriteLine("\tZ: " + CPU.Registers.P.Z);

            Console.WriteLine("Top of stack:");
            Console.WriteLine("\t" + CPU.Stack.Peek());
        }

        public static void ExecuteInstruction(byte instruction)
        {
            if ((instruction >= 0) && (instruction < OpcodeMapper.Map.Length))
            {              
                    Console.WriteLine("Executing Instruction: " + OpcodeMapper.Map[instruction].GetType() + " with argument: " + OpcodeMapper.Map[instruction].Argument);
                    OpcodeMapper.Map[instruction].Execute();
            }
            else
            {
                Console.WriteLine("Instruction out of bounds");
            }
        }

    }
}
